package pl.elka.simulator.gui.swt.painting;

import java.util.HashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.swt.SWT;
import org.eclipse.swt.events.PaintEvent;
import org.eclipse.swt.events.PaintListener;
import org.eclipse.swt.graphics.Color;
import org.eclipse.swt.graphics.GC;

import pl.elka.simulator.core.AreaConstraint;
import pl.elka.simulator.core.Constraint;
import pl.elka.simulator.core.GravityPoint;
import pl.elka.simulator.core.IPaintable;
import pl.elka.simulator.core.Node;
import pl.elka.simulator.core.Pair;
import pl.elka.simulator.core.Position;
import pl.elka.simulator.core.Simulator;
import pl.elka.simulator.core.Treasure;
import pl.elka.simulator.core.experiment.NodePath;
import pl.elka.simulator.core.mobilityManager.impl.nodes.LeaderNode;
import pl.elka.simulator.gui.swt.PositionConverter;
import pl.elka.simulator.gui.swt.SWTMain;
import pl.elka.simulator.gui.swt.PositionConverter.CameraHints;
import pl.elka.simulator.mediator.ActionResult;
import pl.elka.simulator.mediator.ActionType;
import pl.elka.simulator.mediator.ConstraintParts;
import pl.elka.simulator.mediator.SimulationFasade;

public class SimulationPainter implements PaintListener{
	
	private Color sectionColor;
	private Color bigSectionColor;
	private Color zeroSectionColor;	
	private Map<Class, IElementPainter> painters = new HashMap<Class, IElementPainter>(){		
		private static final long serialVersionUID = 1L;

		{
			put(Node.class, new NodePainter());
			put(Constraint.class,new ConstraintPainter());
			put(ConstraintParts.class,new ConstraintPartsPainter());
			put(Treasure.class,new TreasurePainter());
			put(NodePath.class, new PathPainter());
			put(GravityPoint.class, new GravityPointPainter());
			put(AreaConstraint.class, new AreaConstraintPainter());
			put(LeaderNode.class, new LeaderPainter());
		}
	};
	
	@Override
	public void paintControl(PaintEvent e) {
		e.gc.setAntialias(SWT.ON);
		ActionResult result = SimulationFasade.getInstance().handleAction(ActionType.GetVisibleElements, null);
		
//		Node n = new Node(new Position(-0.23458949f, 0.14518704f));
//		paint(n,e);
//		
//		ConstraintParts cp1 = new ConstraintParts();
//		cp1.addPart(new Position(-0.1325507f,0.00899002f));
//		cp1.addPart(new Position(-0.12935805f,0.0047286083f));
//		paint(cp1,e);
//		
//		ConstraintParts cp2 = new ConstraintParts();
//		cp2.addPart(new Position(-0.27540982f,0.15405405f));
//		cp2.addPart(new Position(0.209836f,0.048648655f));
//		paint(cp2,e);
			
		drawVisibleSectors(e);
		
		List<IPaintable> toPaint = (List<IPaintable>)result.getResult();		
		for(IPaintable element:toPaint){
			paint(element,e);
		}				
	}

	private void drawVisibleSectors(PaintEvent e) {
		if(sectionColor == null){
			sectionColor = e.display.getSystemColor(SWT.COLOR_GRAY);
		}
		if(bigSectionColor == null){
			bigSectionColor = e.display.getSystemColor(SWT.COLOR_BLACK);
		}
		if(zeroSectionColor == null){
			zeroSectionColor = e.display.getSystemColor(SWT.COLOR_GREEN);
		}
		
		Pair<Integer, Integer> middlePoint = PositionConverter.convertFromPosition(new Position(0,0));
		int wLimit = SWTMain.DRAW_BOARD_W;
		int hLimit = SWTMain.DRAW_BOARD_H;
		int wStep = Math.max(PositionConverter.convertToScreenW(Simulator.SECTOR_WIDTH),1);
		int hStep = Math.max(PositionConverter.convertToScreenH(Simulator.SECTOR_WIDTH),1);
		
		e.gc.setForeground(sectionColor);
		
		for(int i=middlePoint.left,lineCounter=0;i<=wLimit;i+=wStep,++lineCounter){
			if(lineCounter==0){
				e.gc.setForeground(zeroSectionColor);
				e.gc.drawLine(i, 0, i, SWTMain.DRAW_BOARD_H);
				e.gc.setForeground(sectionColor);
			}
			else if(lineCounter%10 ==0){
				e.gc.setForeground(bigSectionColor);
				e.gc.drawLine(i, 0, i, SWTMain.DRAW_BOARD_H);
				e.gc.setForeground(sectionColor);
			}
			else{
				if(CameraHints.scale<4){
					e.gc.drawLine(i, 0, i, SWTMain.DRAW_BOARD_H);
				}
			}			
		}
		
		for(int i=middlePoint.left,lineCounter=0;i>=0;i-=wStep,++lineCounter){
			if(lineCounter==0){
				e.gc.setForeground(zeroSectionColor);
				e.gc.drawLine(i, 0, i, SWTMain.DRAW_BOARD_H);
				e.gc.setForeground(sectionColor);
			}
			else if(lineCounter%10 ==0){
				e.gc.setForeground(bigSectionColor);
				e.gc.drawLine(i, 0, i, SWTMain.DRAW_BOARD_H);
				e.gc.setForeground(sectionColor);
			}
			else{
				if(CameraHints.scale<4){
					e.gc.drawLine(i, 0, i, SWTMain.DRAW_BOARD_H);
				}
			}
		}
		
		for(int i=middlePoint.right,lineCounter=0;i<=hLimit;i+=hStep,++lineCounter){
			if(lineCounter==0){
				e.gc.setForeground(zeroSectionColor);
				e.gc.drawLine(0, i, SWTMain.DRAW_BOARD_W,i);
				e.gc.setForeground(sectionColor);
			}
			else if(lineCounter%10 ==0){
				e.gc.setForeground(bigSectionColor);
				e.gc.drawLine(0, i, SWTMain.DRAW_BOARD_W,i);
				e.gc.setForeground(sectionColor);
			}
			else{
				if(CameraHints.scale<4){
					e.gc.drawLine(0, i, SWTMain.DRAW_BOARD_W,i);
				}
			}
		}
		
		for(int i=middlePoint.right,lineCounter=0;i>=0;i-=hStep,++lineCounter){
			if(lineCounter==0){
				e.gc.setForeground(zeroSectionColor);
				e.gc.drawLine(0, i, SWTMain.DRAW_BOARD_W,i);
				e.gc.setForeground(sectionColor);
			}
			else if(lineCounter%10 ==0){
				e.gc.setForeground(bigSectionColor);
				e.gc.drawLine(0, i, SWTMain.DRAW_BOARD_W,i);
				e.gc.setForeground(sectionColor);
			}
			else{
				if(CameraHints.scale<4){
					e.gc.drawLine(0, i, SWTMain.DRAW_BOARD_W,i);
				}
			}
		}
		
	}

	private void paint(IPaintable element,PaintEvent e) {
		IElementPainter painter = painters.get(element.getClass());
		if(painter!=null){
			painter.paint(element, e);
		}		
	}

}

